// OpitionsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RigCalib.h"
#include "OpitionsDlg.h"
#include "DeckLinkAPI_h.h"
#include "cvxLog.h"
#include "cvxImage.h"


// COpitionsDlg dialog

IMPLEMENT_DYNAMIC(COpitionsDlg, CDialog)

COpitionsDlg::COpitionsDlg(CWnd* pParent /*=NULL*/)
	: CDialog(COpitionsDlg::IDD, pParent)
{

}

COpitionsDlg::~COpitionsDlg()
{
}

void COpitionsDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_OPITIONS_INPUT_DEVICE, m_inputDevice);
	DDX_Control(pDX, IDC_OPITIONS_VIDEO_FORMAT, m_videoFormat);
	DDX_Control(pDX, IDC_OPINION_PIXEL_FROMAT, m_pixelFormat);
	DDX_Control(pDX, IDC_OPINIONS_STEREO, m_stereoCheck);
	DDX_Control(pDX, IDC_CHECK_FLIP_RIGHT_V, m_flipRightV);
	DDX_Control(pDX, IDC_CAMERA_NAME, m_cameraName);
	DDX_Control(pDX, IDC_SUPPORT_ZOOM_LEVELS, m_supportZoomLevels);
	DDX_Control(pDX, IDC_NEED_CALIB, m_startCalib);
	DDX_Control(pDX, IDC_EDIT_OP_FL, m_opFocalLength);
	DDX_Control(pDX, IDC_OP_SHOW_IA, m_opShowIA);
	DDX_Control(pDX, IDC_DENSE_CALIB, m_opDenseCalib);
	DDX_Control(pDX, IDC_COMBO1, m_captureFPS);
}


BEGIN_MESSAGE_MAP(COpitionsDlg, CDialog)
	ON_CBN_SELCHANGE(IDC_OPITIONS_VIDEO_FORMAT, &COpitionsDlg::OnCbnSelchangeOpitionsVideoFormat)
	ON_BN_CLICKED(IDC_OPINIONS_STEREO, &COpitionsDlg::OnBnClickedOpinionsStereo)
	ON_CBN_SELCHANGE(IDC_OPINION_PIXEL_FROMAT, &COpitionsDlg::OnCbnSelchangeOpinionPixelFromat)
	ON_BN_CLICKED(IDC_LOAD_CAMERA_CONFIGURE, &COpitionsDlg::OnBnClickedLoadCameraConfigure)
	ON_BN_CLICKED(IDC_NEED_CALIB, &COpitionsDlg::OnBnClickedNeedCalib)
	ON_CBN_SELCHANGE(IDC_SUPPORT_ZOOM_LEVELS, &COpitionsDlg::OnCbnSelchangeSupportZoomLevels)
	ON_BN_CLICKED(IDC_OP_SHOW_IA, &COpitionsDlg::OnBnClickedOpShowIa)
	ON_BN_CLICKED(IDC_DENSE_CALIB, &COpitionsDlg::OnBnClickedDenseCalib)
END_MESSAGE_MAP()


// COpitionsDlg message handlers




BOOL COpitionsDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  Add extra initialization here

	//init decklink 
	m_videoFormat.SetItemData(m_videoFormat.AddString("1920 X 1080 60i"), bmdModeHD1080i5994);
//	m_videoFormat.SetItemData(m_videoFormat.AddString("1080 X 720  60p"), bmdModeHD720p60);
	m_videoFormat.SetCurSel(0);

	m_pixelFormat.SetItemData(m_pixelFormat.AddString("8 Bit YUV"), bmdFormat8BitYUV);
//	m_pixelFormat.SetItemData(m_pixelFormat.AddString("8 Bit BGRA"), bmdFormat8BitBGRA);
	m_pixelFormat.SetCurSel(0);

	m_stereoCheck.SetCheck(BST_UNCHECKED);
	m_flipRightV.SetCheck(BST_UNCHECKED);

	//init camera
	m_cameraName.SetWindowText("No camera. Please load.");
	m_supportZoomLevels.SetItemData(m_supportZoomLevels.AddString("None"), -1);
	m_supportZoomLevels.SetCurSel(0);
	m_startCalib.ShowWindow(FALSE);
	

	//init camera focal length
	m_opFocalLength.SetWindowText("No focal length!");	

	//show IA is disabled when calib is distabled
	m_opShowIA.ShowWindow(FALSE);

	//dense calibration
	m_opDenseCalib.ShowWindow(FALSE);
	m_opDenseCalib.SetCheck(BST_UNCHECKED);
	
	//fps
	m_captureFPS.SetItemData(m_captureFPS.AddString(_T("0.5")), 0);
	m_captureFPS.SetItemData(m_captureFPS.AddString(_T("  1")), 1);
	m_captureFPS.SetCurSel(1);

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}


void COpitionsDlg::OnCbnSelchangeOpitionsVideoFormat()
{
	// TODO: Add your control notification handler code here
}



void COpitionsDlg::OnBnClickedOpinionsStereo()
{
	// TODO: Add your control notification handler code here
}

void COpitionsDlg::OnCbnSelchangeOpinionPixelFromat()
{
	// TODO: Add your control notification handler code here
}

void COpitionsDlg::AddDeviceName(const CString & name)
{
	m_inputDevice.AddString(name);
	m_inputDevice.SetCurSel(m_inputDevice.GetCount() - 1);
}
CvSize COpitionsDlg::GetSize()
{
	BMDDisplayMode displayMode = (BMDDisplayMode)m_videoFormat.GetItemData(m_videoFormat.GetCurSel());
	if (displayMode == bmdModeHD1080i5994)
	{
		return cvSize(1920, 1080);
	}
	else if (displayMode == bmdModeHD720p60)
	{
		return cvSize(1280, 720);
	}
	else
	{
		return cvSize(-1, -1);
	}
}
bool COpitionsDlg::Binocular()
{
	return (m_stereoCheck.GetCheck() == BST_CHECKED);
}
void COpitionsDlg::GetFormat(BMDDisplayMode &displayMode,	BMDPixelFormat &pixelFormat, int &flag)
{
	displayMode = (BMDDisplayMode)m_videoFormat.GetItemData(m_videoFormat.GetCurSel());
	pixelFormat = (BMDPixelFormat)m_pixelFormat.GetItemData(m_pixelFormat.GetCurSel());
	int is3D = m_stereoCheck.GetCheck();
	if (is3D == BST_CHECKED)
	{
		flag = bmdVideoInputDualStream3D;			
	}
	else
	{
		flag = bmdVideoInputFlagDefault;
	}
}
int COpitionsDlg::GetChannels()
{
	BMDPixelFormat pixelFormat = (BMDPixelFormat)m_pixelFormat.GetItemData(m_pixelFormat.GetCurSel());
	if (pixelFormat == bmdFormat8BitYUV)
	{
		return 1;
	}	
	else
	{
		AfxMessageBox(_T("pixel format not defined."), MB_OK);
		return S_FALSE;
	}

}
int COpitionsDlg::GetRightFlipFlag(void)
{
	if (m_flipRightV.GetCheck() == BST_CHECKED)
	{
		return 1;
	}
	else
	{
		return -2;
	}
}
bool COpitionsDlg::startCalib()
{
	return (m_startCalib.IsWindowEnabled() == TRUE) && (m_startCalib.GetCheck() == BST_CHECKED);
}
bool COpitionsDlg::isShowIA()
{
	return (m_opShowIA.IsWindowEnabled() == TRUE) &&(m_opShowIA.GetCheck() == BST_CHECKED);
}
bool COpitionsDlg::isDenseCalib()
{
	return (m_opDenseCalib.IsWindowEnabled() == TRUE) && (m_opDenseCalib.GetCheck() == BST_CHECKED);
}
void COpitionsDlg::GetCameraConfigure(SCameraConfigure &left, SCameraConfigure &right)
{
	int zoomLevel = m_supportZoomLevels.GetItemData(m_supportZoomLevels.GetCurSel());
	for (int i = 0; i<m_configures.size(); ++i)
	{
		if (zoomLevel == m_configures[i].zoomLevel)
		{
			left = m_configures[i].left;
			right = m_configures[i].right;
			return;
		}
	}
	AfxMessageBox(_T("Get CameraConfigure Failed!"), MB_OK);
}

float COpitionsDlg::GetFps()
{
	int fps = (int)m_captureFPS.GetItemData(m_captureFPS.GetCurSel());
	if (fps == 0)
	{
		return 0.5;
	}
	else
	{
		return (float)fps;
	}
}

void COpitionsDlg::OnBnClickedLoadCameraConfigure()
{
	// TODO: Add your control notification handler code here

	//load camera configure file
	int isOk = AfxMessageBox(_T("Load Camera Configure"), MB_OKCANCEL);
	string strFile;	
	if (isOk == IDOK)
	{
		CFileDialog iFileDlg(true);
		if (iFileDlg.DoModal()==IDOK)
		{
			strFile = iFileDlg.GetPathName();			
		}
		if (!strFile.empty())
		{
			m_configures.clear();
			FILE *fp = fopen(strFile.c_str(), "r");
			int num = -1;
			if (fp)
			{
				char line[256] = {NULL};
				if(fgets(line, 256, fp) != NULL)
				{
					const char *pCanon = "CANON_XF_105";
					int tn = sizeof("CANON_XF_105");
					if (strncmp(line, pCanon, tn-1) != 0)
					{
						CString str;
						str.Format("%s is not support!\n", line);
						AfxMessageBox(str, MB_OK);						
					}
					else
					{
						//total level numbers
						memset(line, NULL, sizeof(line));
						fgets(line, 256, fp);
						if(sscanf(line, "%d", &num) == 1)
						{
							assert(num != -1);							
							for (int i = 0; i<num; ++i)
							{
								SCameraRigConfigure rig;								
								//zoom level
								memset(line, NULL, sizeof(line));
								fgets(line, 256, fp);
								if (sscanf(line, "%d", &rig.zoomLevel) != 1)
								{
						//			sprintf(g_error, "rig zoom level read error!\n");
									break;
								}								
								//camera intrinsic parameters
								//left 
								memset(line, NULL, sizeof(line));
								fgets(line, 256, fp);
								if (sscanf(line, "%f %f %f %f %f %f %f %f %f %f", 
									&rig.left.fx, &rig.left.fy,
									&rig.left.cx, &rig.left.cy, 
									&rig.left.k1, &rig.left.k2, 
									&rig.left.p1, &rig.left.p2, 
									&rig.left.k3, &rig.left.fl) != 10)
								{
									AfxMessageBox(_T("Load Left Camera Configure failed"), MB_OK);
									break;
								}
								//right camera
								memset(line, NULL, sizeof(line));
								fgets(line, 256, fp);
								if (sscanf(line, "%f %f %f %f %f %f %f %f %f %f", 
									&rig.right.fx, &rig.right.fy,
									&rig.right.cx, &rig.right.cy, 
									&rig.right.k1, &rig.right.k2, 
									&rig.right.p1, &rig.right.p2, 
									&rig.right.k3, &rig.right.fl) != 10)
								{
									AfxMessageBox(_T("Load Right Camera Configure failed"), MB_OK);
									break;
								}
								m_configures.push_back(rig);
							}
						}

					}
				}
			}
			if (fp)
			{
				fclose(fp);
			}

			//update UI
			if (m_configures.size() == num && num > 0)
			{
				m_cameraName.SetWindowText("Canon XF105");
				for (int i = m_supportZoomLevels.GetCount()-1; i >= 0; i--)
				{
					m_supportZoomLevels.DeleteString( i );
				}

				for (int i = 0; i<m_configures.size(); ++i)
				{
					char charNum[256] = {NULL};
					sprintf(charNum, "%d", m_configures[i].zoomLevel, i);
					m_supportZoomLevels.SetItemData(m_supportZoomLevels.AddString(charNum), 
													m_configures[i].zoomLevel);
				}
				m_supportZoomLevels.SetCurSel(0);
				m_startCalib.ShowWindow(TRUE);
		//		m_opShowIA.ShowWindow(TRUE);
				m_opDenseCalib.ShowWindow(TRUE);

				//print out focal length
				int zoomLevel = m_supportZoomLevels.GetItemData(m_supportZoomLevels.GetCurSel());
				for (int i = 0; i<m_configures.size(); ++i)
				{
					if (zoomLevel == m_configures[i].zoomLevel)
					{
						//print out focal length
						char buf[256] = {NULL};
						sprintf(buf, "L: %.2f mm \r\nR: %.2f mm", m_configures[i].left.fl, m_configures[i].right.fl);
						m_opFocalLength.SetWindowText(buf);
						break;
					}
				}
			}
			else
			{
				m_configures.clear();
				AfxMessageBox(_T("Load Camera Configure failed"), MB_OK);
			}
		}
	}

}

void COpitionsDlg::OnBnClickedNeedCalib()
{
	// TODO: Add your control notification handler code here
	if (m_startCalib.GetCheck() == BST_UNCHECKED)
	{
		//show IA is disabled when calib is disabled		
		m_opShowIA.SetCheck(BST_UNCHECKED);
	//	m_opShowIA.ShowWindow(FALSE);
	}
	else
	{
	//	m_opShowIA.ShowWindow(TRUE);
		m_opDenseCalib.SetCheck(BST_UNCHECKED);
	}
}

void COpitionsDlg::OnCbnSelchangeSupportZoomLevels()
{
	// TODO: Add your control notification handler code here

	//update focal length
	int zoomLevel = m_supportZoomLevels.GetItemData(m_supportZoomLevels.GetCurSel());
	for (int i = 0; i<m_configures.size(); ++i)
	{
		if (zoomLevel == m_configures[i].zoomLevel)
		{
			//print out focal length
			char buf[256] = {NULL};
			sprintf(buf, "L: %.2f mm \r\nR: %.2f mm", m_configures[i].left.fl, m_configures[i].right.fl);
			m_opFocalLength.SetWindowText(buf);
			return;
		}
	}
}

void COpitionsDlg::OnBnClickedOpShowIa()
{
	// TODO: Add your control notification handler code here
	if (m_opShowIA.GetCheck() == BST_CHECKED)
	{
		int ret = AfxMessageBox(_T("Make sure the cameras are parallel."), MB_OKCANCEL);
		if (ret == IDCANCEL)
		{
			m_opShowIA.SetCheck(BST_UNCHECKED);
		}
	}
}

void COpitionsDlg::OnBnClickedDenseCalib()
{
	// TODO: Add your control notification handler code here
	if (m_opDenseCalib.GetCheck() == BST_CHECKED)
	{
		m_startCalib.SetCheck(BST_UNCHECKED);
		m_opShowIA.SetCheck(BST_UNCHECKED);
	}
}
